#include <multi_varible_regression.hpp>

#include <iostream>
#include <cmath>

Data hypothetical(const DataVector &Xi, const DataVector &theta) {
    int m = Xi.size();
    if (theta.size() != m) {
        std::cerr << "hypothetical: the size is not matched." << std::endl;
        return {};
    }
    Data h = 0;
    for (size_t j = 0 ; j < m ; j ++ ) {
        h += Xi[j] * theta[j];
    }
    return h;
}

Data costFunction(const DataMatrix &X, const DataVector &Y, const DataVector &theta) {
    size_t n = X.size();
    Data J = 0;
    for (size_t i = 0 ; i < n ; i ++ ) {
        J += powl(hypothetical(X[i], theta) - Y[i], 2);
    }
    J /= (Data) (2 * n);
    return J;
}

Data costFunctionDerivation
    (const DataMatrix &X, const DataVector &Y, const DataVector &theta, size_t j) {
    size_t n = X.size(), m = X[0].size();
    Data derivation = 0;
    for (size_t  i = 0 ; i < n ; i ++ ) {
        derivation += (hypothetical(X[i], theta) - Y[i]) / n * X[i][j]; 
    }
    return derivation;
}

DataVector multipleLinearRegression
    (const DataMatrix &X, const DataVector &Y, 
    Data learningRate) {

    size_t n = X.size();
    if (Y.size() != n) {
        std::cerr << "multipleLinearRegression: the size is not matched." << std::endl;
        return {};
    }
    size_t m = X[0].size();
    DataVector theta;
    for (size_t j = 0 ; j < m ; j ++ ) {
        theta.push_back(0);
    }

    size_t counter = 0;
    while (true) {
        Data old = costFunction(X, Y, theta);
        for (size_t j = 0 ; j < m ;  j ++ ) {
            Data cd = costFunctionDerivation(X, Y, theta, j);
            theta[j] = theta[j] - learningRate * cd;
        }
        Data current = costFunction(X, Y, theta);
        counter ++;
        if (old == current) {break;}
    }

    std::cout << "迭代次数: " << counter << std::endl;

    return theta;
}